package com.hzcc.hzccblog.module.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzcc.hzccblog.common.Result;
import com.hzcc.hzccblog.common.ResultCodeEnum;
import com.hzcc.hzccblog.common.enums.ArticleEnums;
import com.hzcc.hzccblog.module.dao.ArticleDao;
import com.hzcc.hzccblog.module.entity.dto.AddArticle;
import com.hzcc.hzccblog.module.entity.dto.FindByATypeDto;
import com.hzcc.hzccblog.module.entity.dto.RedisPageDto;
import com.hzcc.hzccblog.module.entity.po.Article;
import com.hzcc.hzccblog.module.service.ArticleService;
import com.hzcc.hzccblog.utils.JSONUtil;
import com.hzcc.hzccblog.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.hzcc.hzccblog.common.Constant.*;

/**
 * @Author 早睡蛋
 * @Date 2022/6/8 10:09:01
 * @Desc:
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleDao, Article> implements ArticleService {

    @Autowired
    private ArticleDao articleDao;
    @Resource
    private RedisUtil redisUtil;

    /**
     * 添加博客文章
     * @param addArticle
     * @return
     */
    @Override
    public Result addArticle(AddArticle addArticle) {
        if (addArticle.getId()==null||addArticle.getId()==""){
            return ArticleEnums.NULLID.getResult();
        }
        Article article = new Article();
        article.setId(addArticle.getId());
        article.setTitle(addArticle.getTitle());
        article.setSummary(addArticle.getSummary());
        article.setType(addArticle.getType());
        article.setContent(addArticle.getContent());
        article.setWriter(addArticle.getWriter());
        article.setType(addArticle.getType());
        article.setCreateTime(String.valueOf(System.currentTimeMillis()));
        article.setUpdateTime(String.valueOf(System.currentTimeMillis()));
        int flag = articleDao.insert(article);
        if (flag>0){
            updateArticleRedis(article);
            return ArticleEnums.isADD.getResult();
        }else {
            return ArticleEnums.noADD.getResult();
        }
    }

    public void updateArticleRedis(Article article){
        redisUtil.setZSet(ARTICLE_LIST,JSONUtil.toString(article), Long.valueOf(article.getCreateTime()));
    }

    /**
     * 获取文章列表
     * @return
     */
    @Override
    public Result getAllArticle() {
        QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("*").last("order by create_time desc");
        List<Article> articleList = articleDao.selectList(queryWrapper);
        return ArticleEnums.OK.getResult().setData(articleList);
    }

    /**
     *按时间分页查询文章列表
     * @param currentPage
     * @param pageSize
     * @return
     */
    @Override
    public Result ArticleByTimePage(int currentPage, int pageSize) {
        Page<Article> articlePage = new Page<>(currentPage,pageSize,true);
        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
        articleQueryWrapper.select("*").last("order by create_time desc");
        IPage<Article> articleIPage = articleDao.selectPage(articlePage,articleQueryWrapper);
        return ArticleEnums.OK.getResult().setData(articleIPage);
    }

    /**
     * 按时间分页查询文章(Redis缓存)
     * @param currentPage
     * @param pageSize
     * @return
     * 0 15-----0 15
     * 1 15-----15 30
     * 2 15-----30 45
     */
    @Override
    public Result articleByTimePageRedis(int currentPage,int pageSize) {
        int start = currentPage*pageSize;
        Set<ZSetOperations.TypedTuple<String>> articleSet = redisUtil.getZSet(ARTICLE_LIST, start, start + pageSize);

        if (!articleSet.isEmpty()){
            List<Article> articleList = new ArrayList<>();
            for (ZSetOperations.TypedTuple<String> tuple : articleSet){
                String value = tuple.getValue();
                articleList.add(JSONUtil.toObject(value,Article.class));
            }
            return ArticleEnums.OK.getResult().setData(articleList);
        }
        RedisPageDto redisPageDto = new RedisPageDto();
        redisPageDto.setCurrentPage(currentPage);
        redisPageDto.setPageSize(pageSize);
        List<Article> articleList = articleDao.articleByTimePageRedis(redisPageDto);
        for (Article ar : articleList){
            redisUtil.setZSet(ARTICLE_LIST,JSONUtil.toString(ar),Long.valueOf(ar.getCreateTime()));
        }
        return ArticleEnums.OK.getResult().setData(articleList);
    }

    /**
     * 通过标签查询文章
     * @param findByATypeDto
     * @return
     */
    @Override
    public Result findArticleByType(FindByATypeDto findByATypeDto) {
        String type = findByATypeDto.getType();
        if (null==type||""==type){
            return articleByTimePageRedis(findByATypeDto.getCurrentPage(), findByATypeDto.getPageSize());
        }
        int start = findByATypeDto.getCurrentPage()*findByATypeDto.getPageSize();
        Set<ZSetOperations.TypedTuple<String>> articleSet = redisUtil.getZSet(ARTICLE_TYPE_LIST+type, start, start + findByATypeDto.getPageSize());
        if (!articleSet.isEmpty()){
            List<Article> articleList = new ArrayList<>();
            for (ZSetOperations.TypedTuple<String> tuple : articleSet){
                String value = tuple.getValue();
                articleList.add(JSONUtil.toObject(value,Article.class));
            }
            return ArticleEnums.OK.getResult().setData(articleList);
        }
        List<Article> articleList = articleDao.articleByType(findByATypeDto);
        for (Article ar : articleList){
            redisUtil.setZSet(ARTICLE_TYPE_LIST+type,JSONUtil.toString(ar),Long.valueOf(ar.getCreateTime()));
        }
        return ArticleEnums.OK.getResult().setData(articleList);
    }

    /**
     * 获取指定文章
     * @param id
     * @return
     */
    @Override
    public Result showOneArticle(String id) {
        Article article = articleDao.showOneArticle(id);
        return ArticleEnums.OK.getResult().setData(article);
    }


}
